import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class SokobanWindow extends JFrame {
	private Graphics g;
	private static final int TILESIZE = 20;
	
	private StaticMap globalMap;
	private GlobalCollections stateCollections;

	private Coord playerPos;
	private Coord originalPlayerPos;
	
	public SokobanWindow(Coord playerPos) {
		globalMap = StaticMap.getStaticMap();
		stateCollections = GlobalCollections.getCollection();
		this.originalPlayerPos = playerPos;
		this.playerPos = new Coord(playerPos);
		
		
		int boardSizeW = TILESIZE*globalMap.boardW+1;
		int boardSizeH = TILESIZE*globalMap.boardH+1;
		
		FlowLayout f = new FlowLayout();
		this.setLayout(f);
		
		this.setBounds(800, 300, boardSizeW+100, boardSizeH+50);		
	
		BufferedImage image = new BufferedImage(boardSizeW, boardSizeH, BufferedImage.TYPE_4BYTE_ABGR);
		g = image.getGraphics();
		JLabel label = new JLabel(new ImageIcon(image));
		this.add(label);	
		this.setVisible(true);
		
		this.addKeyListener(new KeyListener() {
			
			public void keyTyped(KeyEvent e) {}			
			public void keyReleased(KeyEvent e) {}	
			
			public void keyPressed(KeyEvent e) {
				switch(e.getKeyCode()) {
					case (KeyEvent.VK_LEFT):    paintPrev();   break;
					case (KeyEvent.VK_RIGHT):   paintNext();   break;
					case (KeyEvent.VK_A):       animateSolutionFwd();  break;
					case (KeyEvent.VK_D):       animateSolutionRev();  break;
					default: break;
				}
			}
		});	
	}
	

	public void paint(BoardState currentBoard) {
		StaticMap.getStaticMap().paint(g, TILESIZE);
		currentBoard.paint(g, TILESIZE);
		this.repaint();
	}
	

	public void paintNext() {			
		StateList states = stateCollections.getAllGeneratedStates();

		if (states != null) {			
			BoardState bs = states.getNext();
			paint(bs);		
			
			String str;
			
			if (bs.getSuccessor() == null) {
				str = "fwd";
			} else {
				str = "bwd";
			}				
			System.out.println(str + "  # "  + states.getCurrentStateIndex());		
		}
	}
	
	
	public void paintPrev() {		
		StateList states = stateCollections.getAllGeneratedStates();

		if (states != null) {
			BoardState bs = states.getPrev();
			paint(bs);		
			
			String str;
			
			if (bs.getSuccessor() == null) {
				str = "fwd";
			} else {
				str = "bwd";
			}
			System.out.println(str + "  # "  + states.getCurrentStateIndex());		
		}
	}
	
	public void paintNextSolution() {	
		StateList solutionPath = stateCollections.getSolutionPath();	
		
		if (solutionPath != null) {
			paint(solutionPath.getNext());				
			System.out.println("# "  + solutionPath.getCurrentStateIndex());		
		}
	}
	
	public void paintPrevSolution() {		
		StateList solutionPath = stateCollections.getSolutionPath();	
		
		if (solutionPath != null) {
			paint(solutionPath.getPrev());				
			System.out.println("# "  + solutionPath.getCurrentStateIndex());	
		}
	}
	
	public void paintAnimation(BoardState currentBoard, Coord playerPos) {
		StaticMap.getStaticMap().paint(g, TILESIZE);
		currentBoard.paint(g, TILESIZE, playerPos);
		this.repaint();
	}


	private void animateSolutionFwd() {		
		SolutionStateList states = stateCollections.getSolutionPath();
		
		char nextInstruction = states.getCurrentInstruction();

		if (nextInstruction == 'x') {
			playerPos.setValue(originalPlayerPos);
			states.getFirst();
		} else {			
			if (Character.isUpperCase(nextInstruction)) states.getNext();	
			
			switch (nextInstruction) {
			case 'U': case 'u':    playerPos.setToNorthCoord();   break;
			case 'R': case 'r':    playerPos.setToEastCoord();    break;
			case 'D': case 'd':    playerPos.setToSouthCoord();   break;
			case 'L': case 'l':    playerPos.setToWestCoord();    break;
			}
		}
		
		paintAnimation(states.getCurrent(), playerPos);
		states.getNextInstruction();

	}
	
	private void animateSolutionRev() {		
		SolutionStateList states = stateCollections.getSolutionPath();		
		
		char nextInstruction = states.getPrevInstruction();

		if (nextInstruction == 'x') {
			BoardState endState = states.getLast();
			playerPos = endState.getPlayerPos();
			
		} else {			
			if (Character.isUpperCase(nextInstruction)) states.getPrev();	
			
			switch (nextInstruction) {
			case 'D': case 'd':    playerPos.setToNorthCoord();   break;
			case 'L': case 'l':    playerPos.setToEastCoord();    break;
			case 'U': case 'u':    playerPos.setToSouthCoord();   break;
			case 'R': case 'r':    playerPos.setToWestCoord();    break;
			}
		}
		
		paintAnimation(states.getCurrent(), playerPos);
	}
	
}
